package main

import "fmt"

type Subject struct {
	observers []Observer
	context   string
}

func NewSubject() *Subject {
	return &Subject{
		observers: make([]Observer, 0),
	}
}

func (s *Subject) Attach(o Observer) { // 将对象加入其中
	s.observers = append(s.observers, o)
}

func (s *Subject) notify() { // 通知被修改的对象
	for _, o := range s.observers {
		o.Update(s)
	}
}

func (s *Subject) UpdateContext(context string) {
	s.context = context
	s.notify()
}

type Observer interface {
	Update(*Subject)
}

type Reader struct {
	name string
}

func NewReader(name string) *Reader {
	return &Reader{
		name: name,
	}
}

func (r *Reader) Update(s *Subject) {
	fmt.Printf("%s receive %s\n", r.name, s.context)
}

func main() {
	/*
		创建一个（观察者）容器装备观察者reader，将reader对象放入subject容器中，通过观察者修改内容


	*/
	subject := NewSubject()
	reader1 := NewReader("reader1")
	reader2 := NewReader("reader2")
	reader3 := NewReader("reader3")
	subject.Attach(reader1)
	subject.Attach(reader2)
	subject.Attach(reader3)

	subject.UpdateContext("observer mode") // 目标与观察者之间建立了一套触发机制
	// Output:
	// reader1 receive observer mode
	// reader2 receive observer mode
	// reader3 receive observer mode

}

/*
观察者模式
	在现实世界中，许多对象并不是独立存在的，其中一个对象的行为发生改变可能会导致一个或者多个其他对象的行为也发生改变。


观察者（Observer）模式的定义：
	指多个对象间存在一对多的依赖关系，当一个对象的状态发生改变时，所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式，它是对象行为型模式。


观察者模式是一种对象行为型模式，其主要优点如下:
	降低了目标与观察者之间的耦合关系，两者之间是抽象耦合关系。
	目标与观察者之间建立了一套触发机制。


它的主要缺点如下：
	目标与观察者之间的依赖关系并没有完全解除，而且有可能出现循环引用。
	当观察者对象很多时，通知的发布会花费很多时间，影响程序的效率。


# 观察者模式

	观察者模式用于触发联动。
	一个对象的改变会触发其它观察者的相关动作，而此对象无需关心连动对象的具体实现。

*/
